package cn.tedu.csmall.server.aspect; 
 /*
 @Time: 2022/11/1 21:36
 @Author:GShuai
 @File:TimerAspect.class
 @Software:IntelliJ IDEA
*/

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 统计Service方法的执行耗时的切面类
 * @version 0.0.1
 */
@Slf4j
@Component
@Aspect
public class TimerAspect {
    // 切面的通知（Advice），可以是：Around（环绕）、Before、After、AfterThrowing、AfterReturning
    // 其他通知的执行例如：
    // Advice 》》》Before
    // try{
    //     pjp.proceed();
    //     Advice 》》》AfterReturning
    // }catch(Throwable e){
    //      Advice >>>AfterThrowing
    //  }finally{
    //     Advice>>> After
    // }
    @Around("execution(* cn.tedu.csmall.server.service.impl.*.*(..))")
    public Object timer(ProceedingJoinPoint pjp) throws Throwable {
        log.debug("执行了切面方法....");

        long start = System.currentTimeMillis();
        // 调用此方法，将执行业务方法（因为通知中配置的表达式匹配的是业务方法）
        // 注意：调用的proceed()方法是抛出异常的，必须在当前切面方法上声明抛出（不能try...catch）
        // 调用proceed()方法的返回值就是业务方法的返回值,必须作为当前切面方法的返回值
        Object result = pjp.proceed();
        long end = System.currentTimeMillis();
        log.debug("当前切面匹配到的组件类：{}",pjp.getTarget());
        log.debug("当前切面匹配到的方法：{}",pjp.getSignature());
        log.debug("当前切面匹配到的方法的参数列表：{}",pjp.getArgs());
        log.debug("当前业务方法的执行耗时，{}ms",(end-start));
        // [必须]返回调用proceed()返回方法的结果
        return result;
    }
}
